package cn.ilikes.tools.hbase.jpa.query.iquerys;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.Parameter;

import org.apache.hadoop.hbase.client.Result;
import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.clients.AbClient;
import cn.ilikes.tools.hbase.jpa.clients.JPAHBaseClientsException;
import cn.ilikes.tools.hbase.jpa.clients.datahander.DataHander;
import cn.ilikes.tools.hbase.jpa.clients.datahander.JPAHBaseDataHnaderException;
import cn.ilikes.tools.hbase.jpa.clients.nodes.Node;
import cn.ilikes.tools.hbase.jpa.indexs.IndexClient;
import cn.ilikes.tools.hbase.jpa.indexs.IndexManagerException;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.query.JPAHBaseQueryRunTimeException;
import cn.ilikes.tools.hbase.jpa.query.sql.element.KuTable;
import cn.ilikes.tools.hbase.jpa.query.sql.element.Properties;
import cn.ilikes.tools.hbase.jpa.query.sql.element.Properties.Between;
import cn.ilikes.tools.logs.Loggerfactory;

public class JPAHBaseQuery extends JPAQuery {

	private Logger logger = Loggerfactory.instance(JPAHBaseQuery.class);

	public JPAHBaseQuery(String sql) {
		super(sql);
	}

	public String printWhere() {
		KuTable kuTresultable = getKuTable();
		return kuTresultable.toWhere();

	}

	/**
	 * class:ccc and ()
	 * 
	 * @return
	 */
	protected String createLunceQuery(KuTable kuTable, IEntityMetaData entityMetaData) {
		String entityName = kuTable.getTableName();
		String indexQuery = kuTable.createLunceQuery(entityName, entityMetaData);
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "create  lunce query   entity name : " + entityName + "  indexQuery => " + indexQuery);
		return indexQuery;
	}

	public String createLunceQuery() {
		KuTable kuTable = getKuTable();
		IEntityMetaData entityMetaData = getContext().getHbasePersistenUnitEnv().getEntityMetaDataFactory().selectIEntityMetaDataByEntityName(kuTable.getTableName());
		String indexQuery = createLunceQuery(kuTable, entityMetaData);
		return indexQuery;
	}

	@Override
	public Object queryResult() {
		try {
			KuTable kuTable = getKuTable();

			IEntityMetaData entityMetaData = getContext().getHbasePersistenUnitEnv().getEntityMetaDataFactory().selectIEntityMetaDataByEntityName(kuTable.getTableName());
			if (entityMetaData == null)
				throw new JPAHBaseQueryRunTimeException("not find entity name :  " + kuTable.getTableName() + " ; sql :  " + sql);
			String indexQuery = createLunceQuery(kuTable, entityMetaData);
			IndexClient indexClient = getClient().getIndexClient();
			List keyIds = indexClient.search(indexQuery, entityMetaData);

			DataHander dataHander = getClient().getDataHander();
			Result[] results = dataHander.seach(entityMetaData, keyIds);
			AbClient abClient = (AbClient) getClient();
			List<Object> resultsList = new ArrayList<Object>();
			for (Result result : results) {
				Node node = abClient.ResultToObject(entityMetaData, result);
				resultsList.add(node.getEntity());
			}
			return resultsList;
		} catch (IndexManagerException e) {
			throw new JPAHBaseQueryRunTimeException(e);
		} catch (JPAHBaseDataHnaderException e) {
			throw new JPAHBaseQueryRunTimeException(e);
		} catch (JPAHBaseClientsException e) {
			throw new JPAHBaseQueryRunTimeException(e);
		}
	}

	/**
	 * 
	 * @param parameters
	 * @param properties
	 */
	public static void assignVariable(Map<Parameter<?>, Object> parameters, Properties properties) {
		Object value = properties.getVariable();
		if (value instanceof Between) {
			Between between = (Between) value;
			Between newBetween = properties.new Between();
			{
				if ((between.getStart() instanceof String)) {
					newBetween.setStart(between.getStart());

				}

				if ((between.getEnd() instanceof String)) {
					newBetween.setEnd(between.getEnd());

				}

				for (Entry<Parameter<?>, Object> parameter : parameters.entrySet()) {
					Parameter parameter_ = parameter.getKey();
					if ((":" + parameter_.getName()).equals(between.getStart())) {
						newBetween.setStart(parameter.getValue());

					}
					if ((":" + parameter_.getName()).equals(between.getEnd())) {
						newBetween.setEnd(parameter.getValue());

					}

				}

			}
			properties.setValue(newBetween);
			return;

		} else {
			if (!(properties.getVariable() instanceof String)) {
				properties.setValue(properties.getVariable());
				return;
			}
			// not s=:s
			String varable = (String) properties.getVariable();
			if (!varable.startsWith(":")) {
				properties.setValue(properties.getVariable());
				return;
			}
			for (Entry<Parameter<?>, Object> parameter : parameters.entrySet()) {
				Parameter parameter_ = parameter.getKey();
				if ((":" + parameter_.getName()).equals(properties.getVariable())) {
					properties.setValue(parameter.getValue());
					return;
				}

			}
		}
		throw new JPAHBaseQueryRunTimeException("not find " + properties.getVariable() + " in  parameters ");
	}

}
